#include "./layout.h"

int  omd_layout_load( omd_layout *layout, ocl_context *context, size_t num_particles, size_t num_buffers)
{
	const size_t bytes_per_buffer = num_particles * sizeof(mds_vector);
	assert( layout );
	assert( num_buffers > 0 );
	assert( num_particles > 0 );
	memset( layout, 0, sizeof( omd_layout ) );
	
	ocl_errno       = CL_SUCCESS;
	layout->buffers = MDS_CALLOC_AS(ocl_buffer,num_buffers);
	if( NULL == layout->buffers ) 
		goto ERROR;
	layout->num_buffers = num_buffers;
	
	while( layout->reserved < layout->num_buffers )
	{
		if( ocl_buffer_load(&layout->buffers[ layout->reserved ], 
							context, 
							CL_MEM_READ_WRITE, 
							bytes_per_buffer, 
							NULL) < 0 )
		{
			goto ERROR;
		}
		layout->reserved++;
	}
	
	return 0;
ERROR:
	omd_layout_quit( layout );
	return -1;
}

void omd_layout_quit( omd_layout *layout )
{
	if( layout )
	{
		if( layout->buffers )
		{
			assert( layout->num_buffers > 0 );
			while( layout->reserved > 0 )
			{
				ocl_buffer_quit( & layout->buffers[ --(layout->reserved) ] );
			}
			MDS_FREE_AS(ocl_buffer,layout->buffers,layout->num_buffers);
		}
	}
	memset( layout, 0, sizeof( omd_layout ) );
}

int omd_layout_write( omd_layout *layout, ocl_queue *Q, mds_frame *frame, size_t field, cl_bool blocking )
{
	assert( layout );
	assert( Q );
	assert( frame );
	assert( frame->sets  );
	assert( frame->num_sets > 0 );
	assert( frame->num_particles > 0 );
	assert( field < frame->num_sets );
	assert( field < layout->num_buffers );
	{
		ocl_buffer *buff = &layout->buffers[field];
		return ocl_enqueue_write_buffer(Q, 
										buff,
										blocking, 
										0, 
										buff->SIZE, 
										frame->sets[field],
										OCL_NO_EVENTS);
	}
}

int omd_layout_read( omd_layout *layout, ocl_queue *Q, mds_frame *frame, size_t field, cl_bool blocking )
{
	assert( layout );
	assert( Q );
	assert( frame );
	assert( frame->sets  );
	assert( frame->num_sets > 0 );
	assert( frame->num_particles > 0 );
	assert( field < frame->num_sets );
	assert( field < layout->num_buffers );
	{
		ocl_buffer *buff = &layout->buffers[field];
		return ocl_enqueue_read_buffer(Q, 
									   buff,
									   blocking, 
									   0, 
									   buff->SIZE, 
									   frame->sets[field],
									   OCL_NO_EVENTS);
	}
}




